package com.dashboard.elasticsearch;

import com.dashboard.bean.ApplicationContextUtils;
import com.dashboard.common.domain.BusinessException;
import com.dashboard.common.utils.R;
import com.dashboard.vo.QueryVO;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.beans.*;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author xuxiaoshisb
 */
@Service
@Primary
@Slf4j
public class AbstractElasticsearchOperatorService implements ElasticsearchOperatorService{

    @Autowired
    RestHighLevelClient restHighLevelClient;

    private Map<String, ElasticsearchOperatorService> beansOfType = new LinkedHashMap<>();

    private ElasticsearchOperatorService getElasticsearchOperatorService(ElasticsearchOperatorService elasticsearchOperatorService){
        ApplicationContext applicationContext = ApplicationContextUtils.getApplicationContext();
        if(Objects.isNull(applicationContext)){
            return null;
        }
        if(beansOfType.isEmpty()){
            Map<String, ElasticsearchOperatorService> elasticsearchOperatorServiceMap = applicationContext.getBeansOfType(ElasticsearchOperatorService.class);
            beansOfType = elasticsearchOperatorServiceMap;
        }
        for (Map.Entry<String, ElasticsearchOperatorService> entry : beansOfType.entrySet()) {
            ElasticsearchOperatorService value = entry.getValue();
            if(value.equals(elasticsearchOperatorService)){
                return value;
            }
        }
        return null;
    }

    @Override
    public R doSearch(QueryVO queryVO) {
        ElasticsearchOperatorService elasticsearchOperatorService = getElasticsearchOperatorService(this);
        if(Objects.isNull(elasticsearchOperatorService)){
            return R.error("没有找到具体的实现类去做查询");
        }
        SearchRequest searchRequest = elasticsearchOperatorService.buildSearchRequest(queryVO);
        SearchResponse search = null;
        try {
            search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("查询异常",e);
            return R.error("查询异常");
        }
        return elasticsearchOperatorService.parseElasticsearchResult(search);
    }

    @Override
    public SearchRequest buildSearchRequest(QueryVO queryVO){
        return null;
    }

    @Override
    public R parseElasticsearchResult(SearchResponse searchResponse) {
        return null;
    }

    protected synchronized  Map<String,Object> getIntrospector(QueryVO queryVO){
        Map<String,Object> map = new HashMap<>(32);
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(queryVO.getClass(),Object.class);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            Arrays.stream(propertyDescriptors).forEach(item ->{
                try {
                    Method readMethod = item.getReadMethod();
                    Object invoke = readMethod.invoke(queryVO);
                    item.setValue(item.getName(),invoke);
                    map.put(item.getName(),item.getValue(item.getName()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }


}
